package com.nexus.core.enums;

import com.nexus.core.exception.ServiceException;

import java.util.Arrays;
import java.util.Optional;

/**
 * 枚举基类
 *
 * @Date 2025/8/1 12:04
 * @Author luzhengning
 **/
public interface BaseEnum<V> {


    /**
     * 获取枚举值
     */
    V getValue();

    /**
     * 获取枚举名称
     */
    String getName();


    /**
     * 根据值获取枚举实例
     *
     * @param enumClass 枚举类
     * @param value     枚举值
     * @return 对应的枚举实例
     */
    static <V, E extends Enum<E> & BaseEnum<V>> E getByValue(Class<E> enumClass, V value) {
        if (value == null) {
            return null;
        }
        Optional<E> first = Arrays.stream(enumClass.getEnumConstants())
                .filter(e -> value.equals(e.getValue()))
                .findFirst();
        if (first.isPresent()) {
            return first.get();
        }
        return null;
    }

    /**
     * 根据值获取名称
     *
     * @param enumClass 枚举类
     * @param value     枚举值
     * @return 对应的名称
     * @throws ServiceException 当值无效时抛出异常
     */
    static <V, E extends Enum<E> & BaseEnum<V>> String getNameByValue(Class<E> enumClass, V value) throws ServiceException {
        Enum<E> byValue = getByValue(enumClass, value);
        return byValue.name();
    }

    /**
     * 根据名称获取枚举实例
     *
     * @param enumClass 枚举类
     * @param name      枚举名称
     * @return 对应的枚举实例
     */
    static <V, E extends Enum<E> & BaseEnum<V>> Optional<E> getByName(Class<E> enumClass, String name) {
        if (name == null) {
            return Optional.empty();
        }
        return Arrays.stream(enumClass.getEnumConstants())
                .filter(e -> name.equals(e.getName()))
                .findFirst();
    }

    /**
     * 根据名称获取值
     *
     * @param enumClass 枚举类
     * @param name      枚举名称
     * @return 对应的值
     * @throws ServiceException 当名称无效时抛出异常
     */
    static <V, E extends Enum<E> & BaseEnum<V>> V getValueByName(Class<E> enumClass, String name) throws ServiceException {
        return getByName(enumClass, name)
                .map(BaseEnum::getValue)
                .orElseThrow(() -> new ServiceException("无效的枚举名称: " + name));
    }
}
